/**
 * Copyright (c) 2014.
 */
package konggao.util.code;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author whua
 * @email smtp2006@126.com
 * @version 2014年3月27日下午9:46:44
 */
public class SimpleCodeEngine
{
    private static final Logger log = LoggerFactory.getLogger( SimpleCodeEngine.class );

    public static final String prefix_default = "_";

    /**
     * 文件名的正则表达式
     */
    private String filePattern;

    /**
     * 原型,指文件中的原型字符串要被seeds中的值替换
     */
    private String prototype;

    /**
     * 种子,生成指定种子的文件
     */
    private Set<String> seeds;

    /**
     * 文件名 + prefix + seed,例如:文件名[User.java],prefix[_],seed[Tmall],结果为:User_Tmall.java
     */
    private String prefix = prefix_default;

    /**
     * Key=被替换的字符串, Value=新值
     */
    private Map<String, String> ognlMap;

    /**
     * @param filePattern
     * @param seeds
     * @param prefix
     */
    public SimpleCodeEngine( String filePattern, Set<String> seeds, String prefix )
    {
        super();
        this.filePattern = filePattern;
        this.seeds = seeds;
        this.prefix = prefix;
    }

    public void invoke( File dir, String ext )
        throws Exception
    {
        if ( log.isDebugEnabled() )
        {
            log.debug( "dir:{}", dir.getAbsolutePath() );
        }

        File[] files = dir.listFiles();
        if ( files != null && files.length > 0 )
        {
            for ( File f : files )
            {
                if ( f.isDirectory() )
                {
                    // 如果是目录,递归扫描
                    invoke( f, ext );
                }
                else
                {
                    // 如果是文件
                    execute( f, ext );
                }
            }

        }
    }

    protected void execute( File file, String ext )
        throws Exception
    {
        if ( log.isInfoEnabled() )
        {
            log.debug( "file:{}", file.getAbsolutePath() );
        }
        // 检查文件是否是模板文件
        if ( match( file ) )
        {
            // 读文件
            StringBuilder fileBuilder = readFile( file );
            if ( log.isInfoEnabled() )
            {
                log.debug( "fileContent:\n{}", fileBuilder );
            }
            String fileNameWithNoExt = file.getName().replace( ext, "" );
            // 规则匹配上
            for ( String seed : seeds )
            {
                // 文件绝对路径
                String newSeedFileName = file.getParent() + File.separator + fileNameWithNoExt + prefix + seed + ext;
                if ( log.isInfoEnabled() )
                {
                    log.debug( "newSeedFile:{}", newSeedFileName );
                }
                // 写文件
                FileWriter newSeedFile = new FileWriter( newSeedFileName );
                String tempString = fileBuilder.toString();
                tempString = tempString.replace( fileNameWithNoExt, fileNameWithNoExt + prefix + seed );
                if ( prototype != null )
                {
                    tempString = tempString.replace( prototype, seed );
                }
                tempString = replace( tempString );
                newSeedFile.write( tempString );
                newSeedFile.close();
            }
        }

    }

    /**
     * 校验文件是否满足正则表达式
     * 
     * @param input
     * @return
     */
    private boolean match( File file )
    {
        if ( filePattern == null )
        {
            return true;
        }
        return Pattern.matches( filePattern, file.getName() );
    }

    /**
     * 读取文件内容
     * 
     * @param file
     * @return
     * @throws Exception
     */
    private StringBuilder readFile( File file )
        throws Exception
    {
        StringBuilder sb = new StringBuilder();
        BufferedReader br = new BufferedReader( new FileReader( file ) );
        try
        {
            String line = null;
            while ( ( line = br.readLine() ) != null )
            {
                sb.append( line ).append( "\n" );
            }
        }
        catch ( Exception e )
        {
            log.error( "##readFile## error:{}", e.getMessage() );
        }
        finally
        {
            if ( br != null )
                br.close();
        }

        return sb;
    }

    /**
     * 替换满足正则表达式的文件内容
     * 
     * @param str
     * @return
     */
    private String replace( String str )
    {
        String ret = str;
        if ( ognlMap != null )
        {
            for ( Map.Entry<String, String> entry : ognlMap.entrySet() )
            {
                ret = ret.replaceAll( entry.getKey(), entry.getValue() );
            }
        }
        return ret;
    }

    public String getFilePattern()
    {
        return filePattern;
    }

    public void setFilePattern( String filePattern )
    {
        this.filePattern = filePattern;
    }

    public Set<String> getSeeds()
    {
        return seeds;
    }

    public void setSeeds( Set<String> seeds )
    {
        this.seeds = seeds;
    }

    public String getPrefix()
    {
        return prefix;
    }

    public void setPrefix( String prefix )
    {
        this.prefix = prefix;
    }

    public static String getPrefixDefault()
    {
        return prefix_default;
    }

    public Map<String, String> getOgnlMap()
    {
        return ognlMap;
    }

    public void setOgnlMap( Map<String, String> ognlMap )
    {
        this.ognlMap = ognlMap;
    }

    public String getPrototype()
    {
        return prototype;
    }

    public void setPrototype( String prototype )
    {
        this.prototype = prototype;
    }

}
